home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 4 / Meeting Pearls Vol. IV (1996)(GTI - Schatztruhe)[!].iso / Pearls / libs / bgui / Demos / multicol.c < prev    next >
C/C++ Source or Header  |  1995-04-26  |  35KB  |  795 lines

  1. ;/*
  2. dcc MultiCol.c -proto -mi -ms -mRR -lbgui
  3. quit
  4. */
  5. /*
  6.  *      MULTICOL.C
  7.  *
  8.  *      (C) Copyright 1995 Jaba Development.
  9.  *      (C) Copyright 1995 Jan van den Baard.
  10.  *          All Rights Reserved.
  11.  */
  12.  
  13. #include "democode.h"
  14.  
  15. #include <dos/exall.h>
  16. #include <utility/hooks.h>
  17.  
  18. #include <clib/macros.h>
  19.  
  20. #include <strings.h>
  21. #include <stdio.h>
  22.  
  23. /*
  24. **      This is the data were going to add
  25. **      to the listview object. It is a simple
  26. **      structure in which the file-information
  27. **      is stored. This data is created in the
  28. **      LISTV_Resource hook from a pointer
  29. **      to a ExAllData structure.
  30. **/
  31. typedef struct {
  32.         UBYTE                   fi_FileName[ 108 ];
  33.         UBYTE                   fi_Size[ 11 ];
  34.         UBYTE                   fi_Date[ 32 ];
  35.         BOOL                    fi_IsDir;
  36. } FILEINFO;
  37.  
  38. /*
  39. **      The LISTV_Resource hook is used to create
  40. **      the FILEINFO structures from a struct ExAllData
  41. **      at create time. At delete time the FILEINFO
  42. **      structure is simply deallocated.
  43. **/
  44. SAVEDS ASM APTR ResourceHookFunc( REG(a0) struct Hook *hook, REG(a2) Object *obj, REG(a1) struct lvResource *lvr )
  45. {
  46.         struct ExAllData        *ead;
  47.         FILEINFO                *fi;
  48.         struct DateTime          dt;
  49.         APTR                     return_code = NULL;
  50.  
  51.         /*
  52.         **      What must we do?
  53.         **/
  54.         switch ( lvr->lvr_Command ) {
  55.  
  56.                 case    LVRC_MAKE:
  57.                         /*
  58.                         **      Create a FILEINFO structure.
  59.                         **      BGUI has passed us a pointer to a
  60.                         **      ExAllData structure. Here we
  61.                         **      convert it to a FILEINFO structure
  62.                         **      which, eventually, get's added to
  63.                         **      the listview.
  64.                         **/
  65.                         if ( fi = ( FILEINFO * )AllocVec( sizeof( FILEINFO ), MEMF_PUBLIC )) {
  66.                                 /*
  67.                                 **      Pick up the ExAllData.
  68.                                 **/
  69.                                 ead = ( struct ExAllData * )lvr->lvr_Entry;
  70.                                 /*
  71.                                 **      Copy the name.
  72.                                 **/
  73.                                 strcpy( &fi->fi_FileName[ 0 ], ead->ed_Name );
  74.                                 /*
  75.                                 **      Format the size text. We can do all sorts of
  76.                                 **      fancy stuff here like using the locale.library
  77.                                 **      formatting stuff but hey, it's just a demo ;)
  78.                                 **/
  79.                                 if ( ead->ed_Type < 0 ) {
  80.                                         fi->fi_IsDir = FALSE;
  81.                                         sprintf( &fi->fi_Size[ 0 ], "%ld", ead->ed_Size );
  82.                                 } else {
  83.                                         fi->fi_IsDir = TRUE;
  84.                                         strcpy( &fi->fi_Size[ 0 ], "(dir)" );
  85.                                 }
  86.                                 /*
  87.                                 **      Convert the date to a string.
  88.                                 **/
  89.                                 dt.dat_Stamp    = *(( struct DateStamp * )&ead->ed_Days );
  90.                                 dt.dat_Format   = FORMAT_CDN;
  91.                                 dt.dat_Flags    = DTF_SUBST | DTF_FUTURE;
  92.                                 dt.dat_StrDay   = NULL;
  93.                                 dt.dat_StrDate  = &fi->fi_Date[ 0 ];
  94.                                 dt.dat_StrTime  = NULL;
  95.                                 /*
  96.                                 **      Format date.
  97.                                 **/
  98.                                 DateToStr( &dt );
  99.                                 /*
  100.                                 **      Return a pointer to the created
  101.                                 **      FILEINFO structure.
  102.                                 **/
  103.                                 return_code = ( APTR )fi;
  104.                         }
  105.                         break;
  106.  
  107.                 case    LVRC_KILL:
  108.                         /*
  109.                         **      Simply deallocate the FILEINFO
  110.                         **      structure which has been created with
  111.                         **      LVRC_MAKE above.
  112.                         **/
  113.                         FreeVec( lvr->lvr_Entry );
  114.                         break;
  115.         }
  116.         /*
  117.         **      Pointer to FILEINFO or NULL.
  118.         **/
  119.         return( return_code );
  120. }
  121.  
  122. /*
  123. **      The listview will have three columns.
  124. **
  125. **      Name            Size            Date
  126. **
  127. **      The following globals will contain the maximum
  128. **      width of each of these columns.
  129. **/
  130. UWORD   MaxName, MaxSize, MaxDate;
  131.  
  132. /*
  133. **      This global stores the total width of the
  134. **      listview drawing area.
  135. **/
  136. UWORD   TotalWidth = 0;
  137.  
  138. /*
  139. **      This boolean determines wether the hook must
  140. **      re-compute the column sizes.
  141. **/
  142. BOOL    ReCompCols = TRUE;
  143.  
  144. /*
  145. **      We use 16 pixels as a minimum inner-column spacing.
  146. **/
  147. #define INNER_SPACE                     16
  148.  
  149. /*
  150. **      This routine re-computes the minimum column
  151. **      sizes when necessary.
  152. **/
  153. VOID ReComputeColumns( struct RastPort *rp, Object *obj, UWORD list_width )
  154. {
  155.         FILEINFO                        *fi;
  156.         UWORD                            tmp, total;
  157.  
  158.         /*
  159.         **      A re-computation is necessary when:
  160.         **
  161.         **      1) The ReCompCols flag is TRUE.
  162.         **      2) The with of the listview has changed.
  163.         **/
  164.         if ( ReCompCols || ( TotalWidth != list_width )) {
  165.                 /*
  166.                 **      Our listview also has a title entry.
  167.                 **      Here we compute the default column
  168.                 **      sizes accoording to this title.
  169.                 **/
  170.                 MaxName = TextLength( rp, "Name:", 6 ) + INNER_SPACE;
  171.                 MaxSize = TextLength( rp, "Size:", 6 ) + INNER_SPACE;
  172.                 MaxDate = TextLength( rp, "Date:", 6 );
  173.                 /*
  174.                 **      Now we loop through the entries to find
  175.                 **      out the largest width of the three columns.
  176.                 **/
  177.                 if ( fi = ( FILEINFO * )FirstEntry( obj )) {
  178.                         /*
  179.                         **      Loop until all are done.
  180.                         **/
  181.                         while ( fi ) {
  182.                                 /*
  183.                                 **      Compute width of the Name: column
  184.                                 **      for this entry.
  185.                                 **/
  186.                                 tmp = TextLength( rp, &fi->fi_FileName[ 0 ], strlen( &fi->fi_FileName[ 0 ] )) + INNER_SPACE;
  187.                                 /*
  188.                                 **      Is it bigger than the last one?
  189.                                 **      If so store it.
  190.                                 **/
  191.                                 if ( tmp > MaxName ) MaxName = tmp;
  192.                                 /*
  193.                                 **      Compute width of the Size: column
  194.                                 **      for this entry.
  195.                                 **/
  196.                                 tmp = TextLength( rp, &fi->fi_Size[ 0 ], strlen( &fi->fi_Size[ 0 ] )) + INNER_SPACE;
  197.                                 /*
  198.                                 **      Is it bigger than the last one?
  199.                                 **      If so store it.
  200.                                 **/
  201.                                 if ( tmp > MaxSize ) MaxSize = tmp;
  202.                                 /*
  203.                                 **      Compute width of the Date: column
  204.                                 **      for this entry.
  205.                                 **/
  206.                                 tmp = TextLength( rp, &fi->fi_Date[ 0 ], strlen( &fi->fi_Date[ 0 ] ));
  207.                                 /*
  208.                                 **      Is it bigger than the last one?
  209.                                 **      If so store it.
  210.                                 **/
  211.                                 if ( tmp > MaxDate ) MaxDate = tmp;
  212.                                 /*
  213.                                 **      Pick up the next entry.
  214.                                 **/
  215.                                 fi = ( FILEINFO * )NextEntry( obj, fi );
  216.                         }
  217.                 }
  218.                 /*
  219.                 **      Compute the total columns width.
  220.                 **/
  221.                 total = MaxName + MaxSize + MaxDate;
  222.                 /*
  223.                 **      If there's room left over we
  224.                 **      distribute it between the columns so
  225.                 **      we get a nice even spacing between
  226.                 **      them.
  227.                 **/
  228.                 if ( list_width > total ) {
  229.                         MaxName += ( list_width - total ) >> 1;
  230.                         MaxSize += ( list_width - total ) >> 1;
  231.                 }
  232.                 /*
  233.                 **      All done. Set the re-compute flag to
  234.                 **      FALSE and store the list width.
  235.                 **/
  236.                 ReCompCols = FALSE;
  237.                 TotalWidth = list_width;
  238.         }
  239. }
  240.  
  241. /*
  242. **      The default DrawInfo pens. Just in case we don't
  243. **      get them from the system.
  244. **/
  245. UWORD   DefDriPens[] = {
  246.         0, 1, 1, 2, 1, 3, 1, 0, 2, 1, 2, 1 };
  247.  
  248. /*
  249. **      Listview rendering hook. Here's where the magic starts ;)
  250. **/
  251. SAVEDS ASM UBYTE *DisplayHookFunc( REG(a0) struct Hook *hook, REG(a2) Object *obj, REG(a1) struct lvRender *lvr )
  252. {
  253.         struct TextExtent               te;
  254.         UBYTE                          *str;
  255.         FILEINFO                       *fi = ( FILEINFO * )lvr->lvr_Entry;
  256.         UWORD                          *pens, numc, w, l, cw, h;
  257.  
  258.         /*
  259.         **      Pick up the DrawInfo pen array.
  260.         **/
  261.         pens = lvr->lvr_DrawInfo ? lvr->lvr_DrawInfo->dri_Pens : DefDriPens;
  262.         /*
  263.         **      Pick up the width of the list.
  264.         **/
  265.         w = lvr->lvr_Bounds.MaxX - lvr->lvr_Bounds.MinX + 1;
  266.         /*
  267.         **      Pick up the list left-edge;
  268.         **/
  269.         l = lvr->lvr_Bounds.MinX;
  270.         /*
  271.         **      Pick up the height of the entry.
  272.         **/
  273.         h = lvr->lvr_Bounds.MaxY - lvr->lvr_Bounds.MinY + 1;
  274.  
  275.         /*
  276.         **      First we render the background.
  277.         **/
  278.         SetAPen( lvr->lvr_RPort, lvr->lvr_State == LVRS_SELECTED ? pens[ FILLPEN ] : pens[ BACKGROUNDPEN ] );
  279.         SetDrMd( lvr->lvr_RPort, JAM1 );
  280.  
  281.         RectFill( lvr->lvr_RPort, lvr->lvr_Bounds.MinX,
  282.                                   lvr->lvr_Bounds.MinY,
  283.                                   lvr->lvr_Bounds.MaxX,
  284.                                   lvr->lvr_Bounds.MaxY );
  285.  
  286.         /*
  287.         **      When we are passed a NULL entry pointer
  288.         **      we are presumed to render the title. If your
  289.         **      listview does not have a title simply
  290.         **      recompute the columns and return NULL.
  291.         **      We have a title so here we go.
  292.         **/
  293.         if ( ! fi ) {
  294.                 /*
  295.                 **      Recompute the column sizes. The routine
  296.                 **      itself will decide if it's necessary.
  297.                 **/
  298.                 ReComputeColumns( lvr->lvr_RPort, obj, w );
  299.                 /*
  300.                 **      Set the pen for the title-entry.
  301.                 **/
  302.                 SetAPen( lvr->lvr_RPort, pens[ FILLPEN ] );
  303.         } else {
  304.                 /*
  305.                 **      Set the pen for a non-title entry. Ofcourse
  306.                 **      we can (should?) differenciate between normal and
  307.                 **      selected here but I wont ;)
  308.                 **/
  309.                 if ( fi->fi_IsDir ) SetAPen( lvr->lvr_RPort, pens[ HIGHLIGHTTEXTPEN ] );
  310.                 else                SetAPen( lvr->lvr_RPort, pens[ TEXTPEN ] );
  311.         }
  312.         /*
  313.         **      Obtain Name: column width. We check it against the
  314.         **      total list width so we do not go outside the
  315.         **      given area.
  316.         **/
  317.         cw = MIN( MaxName, w );
  318.  
  319.         /*
  320.         **      Pick up the name string or, when this
  321.         **      is a title call, the string "Name:".
  322.         **/
  323.         str = fi ? &fi->fi_FileName[ 0 ] : ( UBYTE * )"Name:";
  324.  
  325.         /*
  326.         **      Compute the number of character we
  327.         **      can render.
  328.         **/
  329.         numc = TextFit( lvr->lvr_RPort, str, strlen( str ), &te, NULL, 0, cw, h );
  330.  
  331.         /*
  332.         **      If the number of characters is
  333.         **      0 we can stop right here and now.
  334.         **/
  335.         if ( ! numc ) return( NULL );
  336.  
  337.         /*
  338.         **      Move to the correct position
  339.         **      and render the text.
  340.         **/
  341.         Move( lvr->lvr_RPort, l, lvr->lvr_Bounds.MinY + lvr->lvr_RPort->TxBaseline );
  342.         Text( lvr->lvr_RPort, str, numc );
  343.  
  344.         /*
  345.         **      Adjust the left-edge and width to
  346.         **      get past the Name: column.
  347.         **/
  348.         l += cw;
  349.         w  = MAX(( WORD )( w - cw ), 0 );
  350.  
  351.         /*
  352.         **      Obtain Size: column width. We check it against the
  353.         **      total list width so we do not go outside the
  354.         **      given area.
  355.         **/
  356.         cw = MIN( MaxSize, w );
  357.  
  358.         /*
  359.         **      Pick up the size string or, when this
  360.         **      is a title call, the string "Size:".
  361.         **/
  362.         str = fi ? &fi->fi_Size[ 0 ] : ( UBYTE * )"Size:";
  363.  
  364.         /*
  365.         **      Compute the number of character we
  366.         **      can render.
  367.         **/
  368.         numc = TextFit( lvr->lvr_RPort, str, strlen( str ), &te, NULL, 0, cw, h );
  369.  
  370.         /*
  371.         **      If the number of characters is
  372.         **      0 we can stop right here and now.
  373.         **/
  374.         if ( ! numc ) return( NULL );
  375.  
  376.         /*
  377.         **      Move to the correct position
  378.         **      and render the text.
  379.         **/
  380.         Move( lvr->lvr_RPort, l, lvr->lvr_Bounds.MinY + lvr->lvr_RPort->TxBaseline );
  381.         Text( lvr->lvr_RPort, str, numc );
  382.  
  383.         /*
  384.         **      Adjust the left-edge and width to
  385.         **      get past the Size: column.
  386.         **/
  387.         l += cw;
  388.         w  = MAX(( WORD )( w - cw ), 0 );
  389.  
  390.         /*
  391.         **      Obtain Date column width. We check it against the
  392.         **      total list width so we do not go outside the
  393.         **      given area.
  394.         **/
  395.         cw = MIN( MaxDate, w );
  396.  
  397.         /*
  398.         **      Pick up the date string or, when this
  399.         **      is a title call, the string "Date:".
  400.         **/
  401.         str = fi ? &fi->fi_Date[ 0 ] : ( UBYTE * )"Date:";
  402.  
  403.         /*
  404.         **      Compute the number of character we
  405.         **      can render.
  406.         **/
  407.         numc = TextFit( lvr->lvr_RPort, str, strlen( str ), &te, NULL, 0, cw, h );
  408.  
  409.         /*
  410.         **      If the number of characters is
  411.         **      0 we can stop right here and now.
  412.         **/
  413.         if ( ! numc ) return( NULL );
  414.  
  415.         /*
  416.         **      Move to the correct position
  417.         **      and render the text.
  418.         **/
  419.         Move( lvr->lvr_RPort, l, lvr->lvr_Bounds.MinY + lvr->lvr_RPort->TxBaseline );
  420.         Text( lvr->lvr_RPort, str, numc );
  421.  
  422.         /*
  423.         **      Return NULL. This is important. If we return a non-NULL
  424.         **      value the listview class will think it is a pointer to
  425.         **      the text to render and try to render it.
  426.         **/
  427.         return( NULL );
  428. }
  429.  
  430. /*
  431. **      The comparrison hook. We do a simple name, dir/file
  432. **      comparrison here.
  433. **/
  434. SAVEDS ASM LONG CompareHookFunc( REG(a0) struct Hook *hook, REG(a2) Object *obj, REG(a1) struct lvCompare *lvc )
  435. {
  436.         FILEINFO                *a = ( FILEINFO * )lvc->lvc_EntryA;
  437.         FILEINFO                *b = ( FILEINFO * )lvc->lvc_EntryB;
  438.  
  439.         /*
  440.         **      First we do a type comparrison to get the
  441.         **      directories at the top of the list.
  442.         **/
  443.         if ( a->fi_IsDir && ! b->fi_IsDir      ) return( -1L );
  444.         else if ( ! a->fi_IsDir && b->fi_IsDir ) return( 1L );
  445.  
  446.         /*
  447.         **      Otherwise we do a simple, case insensitive,
  448.         **      name string comparrison.
  449.         **/
  450.         return( stricmp( &a->fi_FileName[ 0 ], &b->fi_FileName[ 0 ] ));
  451. }
  452.  
  453. /*
  454. **      A IDCMP hook for the window which allows us
  455. **      to control the listview from the keyboard.
  456. **/
  457. SAVEDS ASM VOID ScrollHookFunc( REG(a0) struct Hook *hook, REG(a2) Object *obj, REG(a1) struct IntuiMessage *msg )
  458. {
  459.         struct Window                   *window;
  460.         Object                          *lv_obj = ( Object * )hook->h_Data;
  461.  
  462.         /*
  463.         **      Obtain window pointer.
  464.         **/
  465.         GetAttr( WINDOW_Window,        obj,    ( ULONG * )&window );
  466.  
  467.         /*
  468.         **      What key is pressed?
  469.         **/
  470.         switch ( msg->Code ) {
  471.  
  472.                 case    0x4C:
  473.                         /*
  474.                         **      UP              - Move entry up.
  475.                         **      SHIFT + UP      - Move page up.
  476.                         **      CTRL + UP       - Move to the top.
  477.                         **/
  478.                         if ( msg->Qualifier & ( IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT ))
  479.                                 SetGadgetAttrs(( struct Gadget * )lv_obj, window, NULL, LISTV_Select, LISTV_Select_Page_Up, TAG_END );
  480.                         else if ( msg->Qualifier & IEQUALIFIER_CONTROL )
  481.                                 SetGadgetAttrs(( struct Gadget * )lv_obj, window, NULL, LISTV_Select, LISTV_Select_First, TAG_END );
  482.                         else
  483.                                 SetGadgetAttrs(( struct Gadget * )lv_obj, window, NULL, LISTV_Select, LISTV_Select_Previous, TAG_END );
  484.                         break;
  485.  
  486.                 case    0x4D:
  487.                         /*
  488.                         **      DOWN            - Move entry down.
  489.                         **      SHIFT + DOWN    - Move page down.
  490.                         **      CTRL + DOWN     - Move to the end.
  491.                         **/
  492.                         if ( msg->Qualifier & ( IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT ))
  493.                                 SetGadgetAttrs(( struct Gadget * )lv_obj, window, NULL, LISTV_Select, LISTV_Select_Page_Down, TAG_END );
  494.                         else if ( msg->Qualifier & IEQUALIFIER_CONTROL )
  495.                                 SetGadgetAttrs(( struct Gadget * )lv_obj, window, NULL, LISTV_Select, LISTV_Select_Last, TAG_END );
  496.                         else
  497.                                 SetGadgetAttrs(( struct Gadget * )lv_obj, window, NULL, LISTV_Select, LISTV_Select_Next, TAG_END );
  498.  
  499.                         break;
  500.  
  501.                 case    0x43:
  502.                 case    0x44:
  503.                         /*
  504.                         **      RETURN or ENTER - Report the listview ID to the event handler.
  505.                         **/
  506.                         DoMethod( obj, WM_REPORT_ID, (( struct Gadget * )lv_obj )->GadgetID, 0L );
  507.                         break;
  508.         }
  509. }
  510.  
  511. /*
  512. **      The hook structures as added to the
  513. **      listview object and window object.
  514. **
  515. **      If your compiler complaints about the
  516. **      HOOKFUNC typedef uncomment the below line.
  517. **/
  518.  
  519. /* typedef ULONG (*HOOKFUNC)(); */
  520.  
  521. struct Hook ResourceHook = { NULL, NULL, (HOOKFUNC)ResourceHookFunc, NULL, NULL };
  522. struct Hook DisplayHook  = { NULL, NULL, (HOOKFUNC)DisplayHookFunc,  NULL, NULL };
  523. struct Hook CompareHook  = { NULL, NULL, (HOOKFUNC)CompareHookFunc,  NULL, NULL };
  524. struct Hook ScrollHook   = { NULL, NULL, (HOOKFUNC)ScrollHookFunc,   NULL, NULL };
  525.  
  526. /*
  527. **      Scan the directory "name".
  528. **/
  529. VOID ScanDirectory( UBYTE *name, Object *obj )
  530. {
  531.         struct ExAllControl             *eac;
  532.         struct ExAllData                *ead, *tmp;
  533.         struct FileInfoBlock            *fib;
  534.         BPTR                             lock;
  535.         BOOL                             ismore;
  536.  
  537.         /*
  538.         **      We need to recompute the columns.
  539.         **/
  540.         ReCompCols = TRUE;
  541.  
  542.         /*
  543.         **      Get a lock to the directory.
  544.         **/
  545.         if ( lock = Lock( name, ACCESS_READ )) {
  546.                 /*
  547.                 **      Allocate a FileInfoBlock structure.
  548.                 **/
  549.                 if ( fib = ( struct FileInfoBlock * )AllocDosObject( DOS_FIB, NULL )) {
  550.                         /*
  551.                         **      Examine the lock.
  552.                         **/
  553.                         if ( Examine( lock, fib )) {
  554.                                 /*
  555.                                 **      Is this a directory?
  556.                                 **/
  557.                                 if ( fib->fib_DirEntryType > 0 ) {
  558.                                         /*
  559.                                         **      Allocate ExAll() control structure.
  560.                                         **/
  561.                                         if ( eac = ( struct ExAllControl * )AllocDosObject( DOS_EXALLCONTROL, NULL )) {
  562.                                                 /*
  563.                                                 **      Set key to NULL.
  564.                                                 **/
  565.                                                 eac->eac_LastKey = NULL;
  566.                                                 /*
  567.                                                 **      Allocate ExAll() buffer.
  568.                                                 **/
  569.                                                 if ( ead = ( struct ExAllData * )AllocVec( 10 * sizeof( struct ExAllData ), MEMF_PUBLIC )) {
  570.                                                         /*
  571.                                                         **      Read directory.
  572.                                                         **/
  573.                                                         do {
  574.                                                                 /*
  575.                                                                 **      Fill buffer.
  576.                                                                 **/
  577.                                                                 ismore = ExAll( lock, ead, 10 * sizeof( struct ExAllData ), ED_DATE, eac );
  578.  
  579.                                                                 /*
  580.                                                                 **      Errors? Done?
  581.                                                                 **/
  582.                                                                 if (( ! ismore ) && ( IoErr() != ERROR_NO_MORE_ENTRIES ))
  583.                                                                         break;
  584.  
  585.                                                                 /*
  586.                                                                 **      Entries read?
  587.                                                                 **/
  588.                                                                 if ( ! eac->eac_Entries )
  589.                                                                         continue;
  590.  
  591.                                                                 /*
  592.                                                                 **      Pick up data pointer.
  593.                                                                 **/
  594.                                                                 tmp = ead;
  595.  
  596.                                                                 /*
  597.                                                                 **      Add the entries.
  598.                                                                 **/
  599.                                                                 do {
  600.                                                                         AddEntry( NULL, obj, tmp, LVAP_SORTED );
  601.                                                                         /*
  602.                                                                         **      Next...
  603.                                                                         **/
  604.                                                                         tmp = tmp->ed_Next;
  605.                                                                 } while ( tmp );
  606.                                                         } while ( ismore );
  607.                                                         /*
  608.                                                         **      Deallocate ExAll() buffer.
  609.                                                         **/
  610.                                                         FreeVec( ead );
  611.                                                 }
  612.                                                 /*
  613.                                                 **      Deallocate ExAll() control structure.
  614.                                                 **/
  615.                                                 FreeDosObject( DOS_EXALLCONTROL, eac );
  616.                                         }
  617.                                 }
  618.                         }
  619.                         /*
  620.                         **      Deallocate FileInfoBlock structure.
  621.                         **/
  622.                         FreeDosObject( DOS_FIB, fib );
  623.                 }
  624.                 /*
  625.                 **      Release lock.
  626.                 **/
  627.                 UnLock( lock );
  628.         }
  629. }
  630.  
  631. /*
  632. **      And were off...
  633. **/
  634. #define ID_QUIT                 1
  635. #define ID_LIST                 2
  636. #define ID_NEWDIR               3
  637.  
  638. VOID StartDemo( void )
  639. {
  640.         struct RDArgs                   *ra;
  641.         struct Window                   *win;
  642.         Object                          *WO_DirWin, *GO_DirList, *GO_Quit, *GO_NewDir;
  643.         FILEINFO                        *fi;
  644.         ULONG                            dname = 0L, signal, rc;
  645.         UBYTE                            name[ 512 ], *ptr;
  646.         BOOL                             running = TRUE;
  647.  
  648.         /*
  649.         **      Parse command line?
  650.         **/
  651.         if ( ra = ReadArgs( "NAME", &dname, NULL )) {
  652.                 /*
  653.                 **      Copy the name into the buffer.
  654.                 **/
  655.                 if ( dname ) strcpy( name, ( UBYTE * )dname );
  656.                 else         name[ 0 ] = 0;
  657.                 /*
  658.                 **      Create the listview object.
  659.                 **/
  660.                 GO_DirList = ListviewObject,
  661.                         LISTV_ResourceHook,             &ResourceHook,
  662.                         LISTV_DisplayHook,              &DisplayHook,
  663.                         LISTV_TitleHook,                &DisplayHook,
  664.                         LISTV_CompareHook,              &CompareHook,
  665.                         GA_ID,                          ID_LIST,
  666.                 EndObject;
  667.                 /*
  668.                 **      Put it in the IDCMP hook.
  669.                 **/
  670.                 ScrollHook.h_Data = ( APTR )GO_DirList;
  671.                 /*
  672.                 **      Create the window.
  673.                 **/
  674.                 WO_DirWin = WindowObject,
  675.                         WINDOW_Title,           "MultiCol",
  676.                         WINDOW_RMBTrap,         TRUE,
  677.                         WINDOW_ScaleWidth,      50,
  678.                         WINDOW_ScaleHeight,     30,
  679.                         WINDOW_AutoAspect,      TRUE,
  680.                         WINDOW_SmartRefresh,    TRUE,
  681.                         WINDOW_IDCMPHookBits,   IDCMP_RAWKEY,
  682.                         WINDOW_IDCMPHook,       &ScrollHook,
  683.                         WINDOW_MasterGroup,
  684.                                 VGroupObject, HOffset( 4 ), VOffset( 4 ), Spacing( 4 ), GROUP_BackFill, SHINE_RASTER,
  685.                                         StartMember,
  686.                                                 VGroupObject,
  687.                                                         StartMember, GO_DirList, EndMember,
  688.                                                         StartMember,
  689.                                                                 GO_NewDir = KeyString( NULL, name, 512, ID_NEWDIR ), FixMinHeight,
  690.                                                         EndMember,
  691.                                                 EndObject,
  692.                                         EndMember,
  693.                                         StartMember,
  694.                                                 HGroupObject,
  695.                                                         VarSpace( DEFAULT_WEIGHT ),
  696.                                                         StartMember, GO_Quit = KeyButton( "_Quit", ID_QUIT ), EndMember,
  697.                                                         VarSpace( DEFAULT_WEIGHT ),
  698.                                                 EndObject, FixMinHeight,
  699.                                         EndMember,
  700.                                 EndObject,
  701.                 EndObject;
  702.  
  703.                 /*
  704.                 **      Window created OK?
  705.                 **/
  706.                 if ( WO_DirWin ) {
  707.                         /*
  708.                         **      Add gadget key.
  709.                         **/
  710.                         if ( GadgetKey( WO_DirWin, GO_Quit, "q" )) {
  711.                                 /*
  712.                                 **      Open the window.
  713.                                 **/
  714.                                 if ( win = WindowOpen( WO_DirWin )) {
  715.                                         /*
  716.                                         **      Obtain signal mask.
  717.                                         **/
  718.                                         GetAttr( WINDOW_SigMask, WO_DirWin, &signal );
  719.                                         /*
  720.                                         **      Read in the directory.
  721.                                         **/
  722.                                         WindowBusy( WO_DirWin );
  723.                                         ScanDirectory( name, GO_DirList );
  724.                                         WindowReady( WO_DirWin );
  725.                                         /*
  726.                                         **      Refresh the list.
  727.                                         **/
  728.                                         RefreshList( win, GO_DirList );
  729.                                         /*
  730.                                         **      Poll messages...
  731.                                         **/
  732.                                         do {
  733.                                                 Wait( signal );
  734.                                                 while (( rc = HandleEvent( WO_DirWin )) != WMHI_NOMORE ) {
  735.                                                         switch ( rc ) {
  736.  
  737.                                                                 case    ID_QUIT:
  738.                                                                 case    WMHI_CLOSEWINDOW:
  739.                                                                         running = FALSE;
  740.                                                                         break;
  741.  
  742.                                                                 case    ID_LIST:
  743.                                                                         /*
  744.                                                                         **      Get selected entry.
  745.                                                                         **/
  746.                                                                         if ( fi = ( FILEINFO * )FirstSelected( GO_DirList )) {
  747.                                                                                 /*
  748.                                                                                 **      Is the entry a directory?
  749.                                                                                 **/
  750.                                                                                 if ( fi->fi_IsDir ) {
  751.                                                                                         /*
  752.                                                                                         **      AddPart() the name to the buffer.
  753.                                                                                         **/
  754.                                                                                         AddPart( name, &fi->fi_FileName[ 0 ], 512 );
  755.                                                                                         /*
  756.                                                                                         **      Refresh the string gadget.
  757.                                                                                         **/
  758.                                                                                         SetGadgetAttrs(( struct Gadget * )GO_NewDir, win, NULL, STRINGA_TextVal, name, TAG_END );
  759.                                                                                         /*
  760.                                                                                         **      Re-read the list.
  761.                                                                                         **/
  762.                                                                                         refreshDir:
  763.                                                                                         WindowBusy( WO_DirWin );
  764.                                                                                         ClearList( win, GO_DirList );
  765.                                                                                         ScanDirectory( name, GO_DirList );
  766.                                                                                         RefreshList( win, GO_DirList );
  767.                                                                                         WindowReady( WO_DirWin );
  768.                                                                                 }
  769.                                                                         }
  770.                                                                         break;
  771.  
  772.                                                                 case    ID_NEWDIR:
  773.                                                                         /*
  774.                                                                         **      Copy the new name to the buffer.
  775.                                                                         **/
  776.                                                                         GetAttr( STRINGA_TextVal, GO_NewDir, ( ULONG * )&ptr );
  777.                                                                         strcpy( name, ptr );
  778.                                                                         goto refreshDir;
  779.                                                         }
  780.                                                 }
  781.                                         } while ( running );
  782.                                 }
  783.                         }
  784.                         /*
  785.                         **      Kill the object.
  786.                         **/
  787.                         DisposeObject( WO_DirWin );
  788.                 }
  789.                 /*
  790.                 **      Delete the ReadArgs structure.
  791.                 **/
  792.                 FreeArgs( ra );
  793.         }
  794. }
  795.